package iosr11.gbase.dao;

import iosr11.contact.dao.ContactsHelper;
import iosr11.contact.dao.ContactsHelperImpl;

import java.io.IOException;
import java.net.URL;
import java.util.logging.Logger;

import com.google.api.gbase.client.FeedURLFactory;
import com.google.api.gbase.client.GoogleBaseEntry;
import com.google.api.gbase.client.GoogleBaseFeed;
import com.google.api.gbase.client.GoogleBaseQuery;
import com.google.api.gbase.client.GoogleBaseService;
import com.google.gdata.util.ServiceException;

public class DAOLocatorImpl implements DAOLocator{
	
	private ContactsHelper contacts;
	
	private static String username = "iosr.team11@gmail.com";
	private static String password = "iosr_team";

	private static DAOLocator factoryInstance;
	
//	private static BeanFactory beanFactory;

	private GoogleBaseService service;
	
	private static String TITLE = "iosr11.base";
	
	private static GoogleBaseFeed staticFeed;
	private static boolean odswiez;
	
	// obsluga odswiezen
	private static int max_pamiec;
	private static int licznik;
//	private static int ilosc_ogolna;
//	private static int ilosc_baza;

	private Logger log = Logger.getLogger("service-log");
	
	private DAOLocatorImpl(){
		log.info("-------->  zostal utworzony DAOLocator");
		
		contacts = new ContactsHelperImpl();
		service = new GoogleBaseService(TITLE);
		odswiez = true;
		max_pamiec=13;
		licznik=0;
		
//		ilosc_ogolna=0;
//		ilosc_baza=0;
//		beanFactory = new ClassPathXmlApplicationContext("application.xml");
		service = new GoogleBaseService(TITLE);
		this.authenticate(username, password);
		
		//teacherBase = new TeacherDAOImpl();
		//marksBase = new MarkDAOImpl();
	}
	
	/*
	@Override
	public Object getDAO(Class entity) {
		String type = entity.getName();
		log.info("zwrot DAO dla elementu klasy: "+type);
		//String type = entity.getTypeName();
		return beanFactory.getBean(type);
	}*/

	public static DAOLocator getInstance(){
		if (factoryInstance==null) factoryInstance=new DAOLocatorImpl();
		return factoryInstance;
	}
	
	@Override
	public boolean addRecord(GoogleBaseEntry entry) {
		String id = this.addRecordReturnId(entry);
		odswiez = true;
		if (id != null){
			entry.setId(id);
			return true;
		}
		else
			return false;
	}

	@Override
	public String addRecordReturnId(GoogleBaseEntry entry) {
		odswiez = true;
		try {
			GoogleBaseEntry afterAdd = service.insert(FeedURLFactory.getDefault().getItemsFeedURL(), entry);
			return afterAdd.getId();
		}
		catch (Exception e){
			e.printStackTrace();
			return null;
		}
	}

	@Override
	public boolean authenticate(String username, String password) {
		try {
			service.setUserCredentials(username, password);
			return contacts.autenticate(username, password);
		}
		catch(Exception e){
			e.printStackTrace();
			log.warning("Autoryzacja do Google Base nie powiodla sie");
			return false;
		}
	}

	@Override
	public ContactsHelper getContactsDAO() {
		return contacts;
	}

	@Override
	public GoogleBaseFeed getGoogleBaseQueryResult(GoogleBaseQuery query) {
//		System.out.println("wysylanie zapytania po raz: "+ilosc_ogolna);
//		ilosc_ogolna++;
		try {
			if (odswiez){
//				System.out.println("ilosc zapytan do bazy: "+ilosc_baza);
//				ilosc_baza++;
				query.setMaxResults(250);
				log.info("wyslanie zapytania do bazy google");
				odswiez=false;
				staticFeed = service.query(query);
				return staticFeed;
			}
			else {
				licznik++;
				if (licznik>=max_pamiec){
					odswiez=true;
					licznik =0;
				}
				log.info("korzystam z danych w pamieci");
				return staticFeed;
			}
		}
		catch (Exception e){
			e.printStackTrace();
			log.warning("wystapil blad przy wysylaniu zapytania do bazy ("+e.getMessage()+")");
			return null;
		}
	}
	
	@Override
	public GoogleBaseFeed getGoogleBaseQueryResult(GoogleBaseQuery query, String key,
			String value) {
		GoogleBaseFeed queryResult = this.getGoogleBaseQueryResult(query);
		if (queryResult == null) {
			log.warning("dane z bazy nie zostaly poprawnie zwrocone queryResult=null");
			return null;
		}
		
		GoogleBaseFeed result = new GoogleBaseFeed();
		for (GoogleBaseEntry entry : queryResult.getEntries()){
			if (entry.getGoogleBaseAttributes().getTextAttribute(key)!=null)
				if (entry.getGoogleBaseAttributes().getTextAttribute(key).equals(value))
					result.addEntry(entry);
		}
		if (result.getEntries().size()<1) {
			log.info("brak rekordow spelniajacych podane kryterium ("+key+" = "+value+")");
			return null;
		}
		return result;
	}

	@Override
	public GoogleBaseFeed getGoogleBaseQueryResultByRef(String key, String value) {
		GoogleBaseQuery query = new GoogleBaseQuery(FeedURLFactory.getDefault().getItemsFeedURL());
		GoogleBaseFeed queryResult = this.getGoogleBaseQueryResult(query);
		if (queryResult == null){
			log.warning("dane z bazy nie zostaly poprawnie zwrocone queryResult=null");
			return null;
		}
		
		GoogleBaseFeed result = new GoogleBaseFeed();
		for (GoogleBaseEntry entry : queryResult.getEntries()){
			if (entry.getGoogleBaseAttributes().getReferenceAttribute(key)!=null){
				System.out.println(entry.getGoogleBaseAttributes().getReferenceAttribute(key));
				if (entry.getGoogleBaseAttributes().getReferenceAttribute(key).equals(value))
					
					result.addEntry(entry);
				}
		}
		if (result.getEntries().size()<1) {
			log.info("brak rekordow spelniajacych podane kryterium ("+key+" = "+value+")");
			return null;
		}
		return result;
	}

	@Override
	public GoogleBaseEntry getRecord(URL url) {
		try {
			return service.getEntry(url);
		}
		catch (ServiceException e){
			e.printStackTrace();
			log.warning("ServiceException dla url: "+url.getPath());
			return null;
		}
		catch (IOException e){
			e.printStackTrace();
			log.warning("IOException");
			return null;
		}
	}

	@Override
	public GoogleBaseEntry getRecord(String id) {
		try {
			URL url = new URL(id);
			return this.getRecord(url);
		}
		catch(Exception e){
			e.printStackTrace();
			log.warning("bledny id - nie powstal url, podany id: "+id);
			return null;
		}
	}

	@Override
	public GoogleBaseFeed selectByKey(GoogleBaseFeed feed, String key,
			String value) {
		GoogleBaseFeed result = new GoogleBaseFeed();
		for (GoogleBaseEntry entry : feed.getEntries()){
			if (entry.getGoogleBaseAttributes().getTextAttribute(key) != null)
				if (entry.getGoogleBaseAttributes().getTextAttribute(key).equals(value))
					result.addEntry(entry);
		}
		return result;
	}	

	@Override
	public GoogleBaseFeed selectByType(GoogleBaseFeed feed, String type) {
		GoogleBaseFeed result = new GoogleBaseFeed();
		for (GoogleBaseEntry entry : feed.getEntries()){
			if (entry.getGoogleBaseAttributes().getItemType().equals(type))
				result.addEntry(entry);
		}
		return result;
	}

	@Override
	public boolean deleteRecord(String id) {
		odswiez = true;
		try {
			URL entryUrl = new URL(id);
			service.delete(entryUrl);
			return true;
		}
		catch (Exception e){
			e.printStackTrace();
			log.warning("zly id lub brak rekordu w bazie, podane id: "+id);
			return false;
		}
	}


	@Override
	public boolean updateRecord(GoogleBaseEntry old_entry,
			GoogleBaseEntry new_entry) {
		odswiez = true;
		try {
			service.update(new URL(old_entry.getId()), new_entry);
			log.info("aktualizacja zakonczona sukcesem");
			return true;
		}
		catch (Exception e){
			e.printStackTrace();
			log.warning("blad przy aktualizacji rekordu");
			return false;
		}
	}
	
}
